 


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel;
using Core;
using IglooCoder.Commons.WcfNhibernate;
using Infrastucture;
using WcfService1.DTO;
using Omu.ValueInjecter;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" CashBankIn to change the class name "CashBankInServices" in code, svc and config file together.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    [NHibernateContext]
    public class CashBankInServices : ICashBankInServices
    {
        private CashBankInRepository CashBankInRepository;
        private JurnalRepository jurnalRepository;
        WcfSessionStorage session;
        public CashBankInServices()
        {
            session = new WcfSessionStorage();
            CashBankInRepository = new CashBankInRepository(session);
            jurnalRepository = new JurnalRepository(session);
        }

        
        public List<CashBankInDTO> GetList(int page, out long recordCount, string sortProperty = null, string sortType = "ASC")
        {
            var CashBankIns = new List<CashBankIn>();
            var Results = new List<CashBankInDTO>();

            if (string.IsNullOrEmpty(sortProperty))
            {
                CashBankIns = CashBankInRepository.GetDataPaged(page, 30).ToList();
            }
            else
            {
                CashBankIns = CashBankInRepository.GetDataPaged(page, 30, sortProperty, sortType).ToList();
            }

            recordCount = CashBankInRepository.RecordCount;

            CashBankIns.ForEach(x =>
                    {

                        CashBankInDTO CashBankInDto = new CashBankInDTO();
                        CashBankInDto.CashBankAccount = new CoaDTO();
                        CashBankInDto.InjectFrom(x);
                        if (x.CashBankAccount != null) CashBankInDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                        Results.Add(CashBankInDto);
                    }
                );

            return Results;
        }

        public bool Save(CashBankInDTO CashBankInDTO)
        {
            bool res = false;
            try
            {
               CashBankInRepository.ExecuteTransactionNative(()=>
                                                                 {
                                                                     var CashBankIn = CashBankInRepository.GetDataOne(x => x.NoVoucher == CashBankInDTO.NoVoucher);

                                                                     if (CashBankIn == null)
                                                                     {
                                                                         CashBankIn = new CashBankIn();

                                                                         CashBankIn.InjectFrom(CashBankInDTO);
                                                                         CashBankIn.CashBankAccount = (COA) new COA().InjectFrom(CashBankInDTO.CashBankAccount);

                                                                         foreach (var cashBankInDetail in CashBankInDTO.CashBankInDetails)
                                                                         {
                                                                             var cashdetail = new CashBankInDetail();
                                                                             cashdetail.InjectFrom(cashBankInDetail);
                                                                             
                                                                             if (cashBankInDetail.SalesInvoice != null)
                                                                             {
                                                                                 cashdetail.SalesInvoice = new SalesInvoice();
                                                                                 cashdetail.SalesInvoice.InjectFrom(cashBankInDetail.SalesInvoice);
                                                                             }
                                                                             if (cashBankInDetail.Departemen != null)
                                                                             {
                                                                                 cashdetail.Departemen = new Departemen();
                                                                                 cashdetail.Departemen.InjectFrom(cashBankInDetail.Departemen);
                                                                             }
                                                                             if (cashBankInDetail.FromAccount != null)
                                                                             {
                                                                                 if (string.IsNullOrEmpty(cashBankInDetail.FromAccount.AccountNumber))
                                                                                     throw  new Exception("COA tidak boleh Kosong!");
                                                                                 cashdetail.FromAccount = new COA();
                                                                                 cashdetail.FromAccount.InjectFrom(cashBankInDetail.FromAccount);
                                                                             }

                                                                             
                                                                             if (cashBankInDetail.Customer != null)
                                                                             {
                                                                                 cashdetail.Customer = new Customer();
                                                                                 cashdetail.Customer.InjectFrom(
                                                                                    cashBankInDetail.Customer);
                                                                             }
                                                                                
                                                                             CashBankIn.CashBankInDetails.Add(cashdetail);
                                                                         }

                                                                         if (String.IsNullOrEmpty(CashBankIn.NoVoucher))
                                                                             if (! string.IsNullOrEmpty(CashBankIn.CashBankAccount.KodeVoucher))
                                                                         {
                                                                             CashBankIn.NoVoucher = GetLastNumber(CashBankIn.CashBankAccount.KodeVoucher);
                                                                         }else
                                                                             {
                                                                                 throw new Exception(CashBankIn.CashBankAccount.AccountName + " KodeVouchernya belum diset!");
                                                                             }

                                                                         foreach (
                                                                             var cashBankInDetail in
                                                                                 CashBankIn.CashBankInDetails)
                                                                             cashBankInDetail.CashBankIn = CashBankIn;
                                                                         
                                                                         CashBankInRepository.SaveOrUpdate(CashBankIn);
                                                                         CreateJurnal(CashBankIn);
                                                                     }else
                                                                     {
                                                                         CashBankInRepository.Delete(CashBankIn);
                                                                         var jurnal =
                                                                             jurnalRepository.FetchById(
                                                                                 CashBankIn.NoVoucher);
                                                                         jurnalRepository.Delete(jurnal);

                                                                         var mutasiPiutangRepo =
                                                                             new MutasiPiutangRepository(session);
                                                                         mutasiPiutangRepo.DeleteMutasiPiutang(CashBankIn.NoVoucher);

                                                                         var cashIn = new CashBankIn();
                                                                         cashIn.InjectFrom(CashBankInDTO);
                                                                         cashIn.CashBankAccount = (COA)new COA().InjectFrom(CashBankInDTO.CashBankAccount);
                                                                         foreach (var cashBankInDetail in CashBankInDTO.CashBankInDetails)
                                                                         {
                                                                             var cashdetail = new CashBankInDetail();
                                                                             cashdetail.InjectFrom(cashBankInDetail);
                                                                             if (cashBankInDetail.SalesInvoice != null && !string.IsNullOrEmpty(cashBankInDetail.SalesInvoice.SINo))
                                                                             {
                                                                                 cashdetail.SalesInvoice = new SalesInvoice();
                                                                                 cashdetail.SalesInvoice.InjectFrom(cashBankInDetail.SalesInvoice);
                                                                             }

                                                                             if (cashBankInDetail.Departemen != null)
                                                                             {
                                                                                 cashdetail.Departemen = new Departemen();
                                                                                 cashdetail.Departemen.InjectFrom(cashBankInDetail.Departemen);
                                                                             }
                                                                             if (cashBankInDetail.FromAccount != null)
                                                                             {
                                                                                 if (string.IsNullOrEmpty(cashBankInDetail.FromAccount.AccountNumber))
                                                                                     throw new Exception("COA tidak boleh Kosong!");
                                                                                 cashdetail.FromAccount = new COA();
                                                                                 cashdetail.FromAccount.InjectFrom(cashBankInDetail.FromAccount);
                                                                             }
                                                                             if (cashBankInDetail.Customer != null)
                                                                             {
                                                                                 cashdetail.Customer = new Customer();
                                                                                 cashdetail.Customer.InjectFrom(
                                                                                    cashBankInDetail.Customer);
                                                                             }
                                                                             cashIn.CashBankInDetails.Add(cashdetail);
                                                                         }

                                                                         foreach (var cashBankInDetail in
                                                                               cashIn.CashBankInDetails)
                                                                             cashBankInDetail.CashBankIn = cashIn;

                                                                         CashBankInRepository.Session.SaveOrUpdateCopy(cashIn);
                                                                         CreateJurnal(cashIn);
                                                                     }
                                                                   
                                                                     res = true;
                                                                 });
               
            }
            catch (Exception)
            {
                throw;
                res = false;
            }

            return res;
        }


        public bool Delete(CashBankInDTO CashBankInDto)
        {
            bool res;
            try
            {
                var CashBankIn = new CashBankIn();
                AutoMapper.Mapper.Map(CashBankInDto, CashBankIn);
                CashBankInRepository.Delete(CashBankIn);
                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public List<CashBankInDTO> GetListByCriteria(Dictionary<String, Object> criteria, string expression, int page, out long recordCount)
        {
            List<CashBankIn> CashBankIns = new List<CashBankIn>();
            var Results = new List<CashBankInDTO>();
            CashBankIns = CashBankInRepository.GetDataPaged(criteria, expression, page, 30).ToList();
            recordCount = CashBankInRepository.RecordCount;
            CashBankIns.ForEach(x =>
                {
                        CashBankInDTO CashBankInDto = new CashBankInDTO();
                        CashBankInDto.InjectFrom(x);
                        Results.Add(CashBankInDto);
                }
            );

            return Results;
        }


        public List<CashBankInDTO> SearchByCriteria(Dictionary<String, Object> criteria, List<String> Operators , int page, out long recordCount)
        {
            List<CashBankIn> CashBankIns = new List<CashBankIn>();
            var Results = new List<CashBankInDTO>();
            CashBankIns = CashBankInRepository.GetDataSearchPaged(criteria, Operators, page, 30).ToList();
            recordCount = CashBankInRepository.RecordCount;
            CashBankIns.ForEach(x =>
            {
                CashBankInDTO CashBankInDto = new CashBankInDTO();
                CashBankInDto.InjectFrom(x);
                Results.Add(CashBankInDto);
            }
            );

            return Results;
        }

        public List<CashBankInDTO> GetAllCashBankIn()
        {
            var CashBankIns = CashBankInRepository.FetchAll().ToList();
            var Results = new List<CashBankInDTO>();
            CashBankIns.ForEach(x =>
                {
                    CashBankInDTO CashBankInDto = new CashBankInDTO();
                    CashBankInDto.CashBankAccount = new CoaDTO();
                    CashBankInDto.InjectFrom(x);
                    if (x.CashBankAccount != null) CashBankInDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                    Results.Add(CashBankInDto);
                }
            );

            return Results;
        }


        public CashBankInDTO GetCashBankIn(String noVoucher)
        {
            var cashBankIn = CashBankInRepository.GetDataOne(x => x.NoVoucher == noVoucher);
            CashBankInDTO cashBankInDto = new CashBankInDTO();
            cashBankInDto.InjectFrom(cashBankIn);
            cashBankInDto.CashBankAccount = new CoaDTO();
            if (cashBankIn.CashBankAccount != null)
                cashBankInDto.CashBankAccount.InjectFrom(cashBankIn.CashBankAccount);
            foreach (var cashBankInDetail in cashBankIn.CashBankInDetails)
            {
                var cashdetail = new CashBankInDetailDTO();
                cashdetail.InjectFrom(cashBankInDetail);
               
                if (cashBankInDetail.SalesInvoice != null)
                {
                    cashdetail.SalesInvoice = new SalesInvoiceDTO();
                    cashdetail.SalesInvoice = new SalesInvoiceDTO() {SINo = cashBankInDetail.SalesInvoice.SINo };
                }
               
                if (cashBankInDetail.Departemen != null)
                {
                    cashdetail.Departemen = new DepartemenDTO();
                    cashdetail.Departemen.InjectFrom(cashBankInDetail.Departemen);
                }
                
                if (cashBankInDetail.FromAccount != null)
                {
                    cashdetail.FromAccount = new CoaDTO();
                    cashdetail.FromAccount.InjectFrom(cashBankInDetail.FromAccount);
                }
               
                if (cashBankInDetail.Customer !=null)
                {
                    cashdetail.Customer = new CustomerDTO();
                    cashdetail.Customer.InjectFrom(cashBankInDetail.Customer);
                    var salesInvoiceServices = new SalesInvoiceServices();
                    cashdetail.SalesInvoices = new ObservableCollection<SalesInvoiceDTO>(salesInvoiceServices.GetSalesInvoiceByCustomer(cashdetail.Customer));
                }
                cashBankInDto.CashBankInDetails.Add(cashdetail);
            }
            return cashBankInDto;
        }

        public List<CashBankInDTO> GetCashBankInList(string noVoucher)
        {
            var CashBankIns = CashBankInRepository.GetDataList(x => x.NoVoucher.Contains(noVoucher)).ToList();
            var Results = new List<CashBankInDTO>();
            CashBankIns.ForEach(x =>
                {
                    CashBankInDTO CashBankInDto = new CashBankInDTO();
                    CashBankInDto.CashBankAccount = new CoaDTO();
                    CashBankInDto.InjectFrom(x);
                    if (x.CashBankAccount != null) CashBankInDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                    Results.Add(CashBankInDto);
                }
            );
            return Results;
        }

        public string GetLastNumber(string kodeBank)
        {
            var appParamServices = new AppParamServices();
            AppParamDTO param = appParamServices.GetAppParamList("KodeCashIn").FirstOrDefault();
            if (param == null) throw new Exception("Parameter KodeCashIn belum diset!");
            string res = CashBankInRepository.GetMaxNumber(kodeBank, param.AppParamValue);

            if (string.IsNullOrEmpty(res))
                res = param.AppParamValue;

            string formatSO = "0000";
            string lastNo = string.Empty;
            string kodeSO;
            if (res.Length <= 4)
            {
                lastNo = formatSO;
                kodeSO = res;
            }
            else
            {
                lastNo = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[4];
                kodeSO = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0];
            }
            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(lastNo) + 1).ToString().Length) +
                           (int.Parse(lastNo) + 1);

            return kodeSO + "/" + kodeBank + "/" + DateTime.Now.Month  + "/" + DateTime.Now.Year + "/" + soNum;
        }


        private void CreateJurnal(CashBankIn cashBankIn)
        {
            var jurnal = new Jurnal();
            jurnal.NoVoucher = cashBankIn.NoVoucher;
            jurnal.TglJurnal = cashBankIn.Tanggal;
            jurnal.ReffNumber = cashBankIn.NoVoucher;
            jurnal.TipeJurnal = typeof (CashBankIn).Name;
            jurnal.Description = cashBankIn.Description;

                foreach (var cashBankInDetail in cashBankIn.CashBankInDetails)
                {
                    var jd = new JurnalDetail();
                    jd.Jurnal = jurnal;

                    jd.AccountNumber = cashBankInDetail.FromAccount.AccountNumber;
                    jd.Debit = cashBankInDetail.Debit;
                    jd.Kredit = cashBankInDetail.Kredit;
                    jd.Departemen = cashBankInDetail.Departemen;
                    jurnal.JurnalDetails.Add(jd);
                }
           
            jurnalRepository.SaveOrUpdate(jurnal);


            if (cashBankIn.CashBankInDetails.Any(x=>x.SalesInvoice != null))
            {
                //Kartu Piutang
                var mutasiPiutangRepo = new MutasiPiutangRepository(session);
                foreach (var cashBankInDetail in cashBankIn.CashBankInDetails.Where(x=>x.SalesInvoice != null))
                {
                    var lastmutasi = mutasiPiutangRepo.FindLastMutasi(cashBankInDetail.Customer.CustomerId, cashBankInDetail.SalesInvoice.SINo,
                                                                      cashBankInDetail.CashBankIn.Tanggal);
                    var mutasiPiutang = new MutasiPiutang();
                    mutasiPiutang.SaldoAwal = lastmutasi.SaldoSisa;
                    mutasiPiutang.SaldoKeluar = cashBankInDetail.Kredit;
                    mutasiPiutang.SaldoSisa = mutasiPiutang.SaldoAwal + mutasiPiutang.SaldoMasuk - mutasiPiutang.SaldoKeluar;
                    mutasiPiutang.CustomerId = cashBankInDetail.Customer.CustomerId;
                    mutasiPiutang.Tanggal = cashBankIn.Tanggal;
                    mutasiPiutang.Type = typeof(SalesInvoice).Name;
                    mutasiPiutang.InvoiceNo = cashBankInDetail.SalesInvoice.SINo;
                    mutasiPiutang.Coa = cashBankInDetail.FromAccount.AccountNumber;
                    mutasiPiutang.ReferenceNumber = cashBankIn.NoVoucher;
                    mutasiPiutangRepo.SaveOrUpdate(mutasiPiutang);
                }
            }
        }

    }

}


